package com.lin.mybatis.service;

import com.lin.mybatis.dao.UserDao;
import com.lin.mybatis.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @作者: 林江
 * @创建时间: 2024/4/26
 * @功能: 对于5000条数据，各种批量操作。
 */
@Service
public class InsertBatchService {
    private int num = 500000;

    @Autowired
    UserDao userDao;

    /**
     * 循环
     */
    public void loopInsertBatch() {
        long start = System.currentTimeMillis();
        for (int i = 1; i <= num; i++) {
            User user = new User();
            user.setName("林江" + i);
            userDao.insert(user);
        }
        System.out.println(System.currentTimeMillis() - start);
    }

    /**
     * 分段插入
     */
    public void fragmentInsertBatch() {
        long start = System.currentTimeMillis();
        List<User> list = new ArrayList<>();
        for (int i = 1; i <= num; i++) {
            User user = new User();
            user.setName("林江" + i);
            list.add(user);

            // 每隔1000条数据开始插入
            if (i % 1000 == 0) {
                userDao.insertBatchSomeColumn(list);
                list.clear(); // 清空数组
            }
        }

        if (list.size() > 0) {
            userDao.insertBatchSomeColumn(list);
        }

        System.out.println(System.currentTimeMillis() - start);
    }

    /**
     * 线程模型下插入
     */
    public void threadInsertBatch() throws InterruptedException {
        long start = System.currentTimeMillis();
        List<User> list = new ArrayList<>();
        for (int i = 1; i <= num; i++) {
            User user = new User();
            user.setName("林江" + i);
            list.add(user);
        }

        int count = list.size();
        int pageSize = 1000; // 每批次插入1000的数据量
        // 线程数
        int threadNum = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(threadNum);
        executor.initialize(); // 初始化线程池

        CountDownLatch countDownLatch = new CountDownLatch(threadNum);
        // 循环线程
        for (int i = 0; i < threadNum; i++) {
            int startIndex = i * pageSize;
            int endIndex = Math.min(count, (i + 1) * pageSize);
            List<User> users = list.subList(startIndex, endIndex);

            executor.execute(() -> {
                try {
                    userDao.insertBatchSomeColumn(users);
                } catch (Exception e) {
                    throw e;
                } finally {
                    System.out.println(Thread.currentThread().getName() + "执行完毕");
                    countDownLatch.countDown();
                }
            });
        }
        System.out.println("等待子线程执行完毕");
        // 等待所有线程执行完毕
        countDownLatch.await();
        executor.shutdown(); // 关闭线程池
        System.out.println(System.currentTimeMillis() - start);
    }

}
